using UnityEngine;
using UnityEngine.UI;

namespace UnityX
{
    [DisallowMultipleComponent]
    [RequireComponent(typeof(CanvasRenderer))]
    [AddComponentMenu("UI/Line 2D")]
    public class Line2D : MaskableGraphic
    {
        [SerializeField]
        private float m_LineWidth = 2;

        private int m_PositionCount = 0;
        private Vector3[] m_Positions = new Vector3[100];

        public float lineWidth
        {
            get
            {
                return m_LineWidth;
            }
            set
            {
                m_LineWidth = value;
                SetAllDirty();
            }
        }
        public int positionCount
        {
            get
            {
                return m_PositionCount;
            }
            set
            {
                if (value > m_Positions.Length)
                {
                    Vector3[] p = new Vector3[value];
                    for (int i = 0; i < m_PositionCount; i++)
                    {
                        p[i] = m_Positions[i];
                    }
                    m_Positions = p;
                }
                m_PositionCount = value;
                SetAllDirty();
            }
        }

        public Vector3 GetPosition(int index)
        {
            return m_Positions[index];
        }
        public Vector3[] GetPositions()
        {
            if (m_Positions.Length == m_PositionCount)
            {
                return m_Positions;
            }
            Vector3[] positions = new Vector3[m_PositionCount];
            for (int i = 0; i < m_PositionCount; i++)
            {
                positions[i] = m_Positions[i];
            }
            return positions;
        }
        public void SetPosition(int index, Vector3 position)
        {
            m_Positions[index] = position;
            SetAllDirty();
        }
        public void SetPositions(Vector3[] positions)
        {
            if (positions.Length > m_Positions.Length)
            {
                m_Positions = new Vector3[positions.Length];
            }
            for (int i = 0; i < positions.Length; i++)
            {
                m_Positions[i] = positions[i];
            }
            m_PositionCount = positions.Length;
            SetAllDirty();
        }
        public void AddPosition(Vector3 position)
        {
            if (m_PositionCount >= m_Positions.Length)
            {
                Vector3[] newPositions = new Vector3[m_Positions.Length + 100];
                for (int i = 0; i < m_Positions.Length; i++)
                {
                    newPositions[i] = m_Positions[i];
                }
                m_Positions = newPositions;
            }
            m_Positions[m_PositionCount] = position;
            m_PositionCount++;
            SetAllDirty();
        }
        public void Simplify(float tolerance)
        {
            for (int i = 1; i < m_PositionCount - 1; i++)
            {
                if (Vector3.Distance(m_Positions[i - 1], m_Positions[i]) < tolerance)
                {
                    for (int j = i; j < m_PositionCount - 1; j++)
                    {
                        m_Positions[j] = m_Positions[j + 1];
                    }
                    m_PositionCount--;
                    i--;
                }
            }
            SetAllDirty();
        }
        public void Clear()
        {
            m_PositionCount = 0;
            SetAllDirty();
        }
        protected override void OnPopulateMesh(VertexHelper vh)
        {
            vh.Clear();
            if (m_PositionCount < 2)
            {
                return;
            }

            Rect rect = GetPixelAdjustedRect();
            float extent = m_LineWidth / 2;

            //中间的点
            for (int i = 0; i < m_PositionCount - 1; i++)
            {
                //右方向
                Vector3 rd = Vector3.Cross(m_Positions[i + 1] - m_Positions[i], Vector3.forward).normalized;

                //右边点
                Vector3 l = m_Positions[i] + (rd * extent);
                //左边点
                Vector3 r = m_Positions[i] - (rd * extent);
                vh.AddVert(l, color, Vector4.zero);
                vh.AddVert(r, color, Vector4.zero);

                //右边点
                Vector3 l2 = m_Positions[i + 1] + (rd * extent);
                //左边点
                Vector3 r2 = m_Positions[i + 1] - (rd * extent);
                vh.AddVert(l2, color, Vector4.zero);
                vh.AddVert(r2, color, Vector4.zero);
            }

            //添加索引
            vh.AddTriangle(0, 1, 2);
            vh.AddTriangle(1, 3, 2);
            for (int i = 1; i < m_PositionCount - 1; i++)
            {
                int ii = i * 4;

                vh.AddTriangle(ii - 2, ii - 1, ii - 0);
                vh.AddTriangle(ii - 1, ii + 1, ii - 0);

                vh.AddTriangle(ii, ii + 1, ii + 2);
                vh.AddTriangle(ii + 1, ii + 3, ii + 2);
            }
        }
#if UNITY_EDITOR
        protected override void Reset()
        {
            raycastTarget = false;
        }
#endif
    }
}